import 'dart:async';

import 'package:async/async.dart';
import 'package:async_test/src/utils.dart';

import '../common/test_page.dart';

class FutureGroupTestPage extends TestPage {
  FutureGroupTestPage(super.title) {
    late FutureGroup futureGroup;
    setUp() {
      futureGroup = FutureGroup();
    }

    group('FutureGroup没有未来', () {
      test('FutureGroup.future.then()如果什么都不发生，就永远不会完成', () async {
        setUp();
        var completed = false;
        futureGroup.future.then((_) => completed = true);

        await flushMicrotasks();
        expect(completed);
      });

      test("关闭后完成", () {
        setUp();
        expect(futureGroup.future);
        expect(futureGroup.isClosed);
        futureGroup.close();
        expect(futureGroup.isClosed);
      });
    });

    group('FutureGroup未来已经完成', () {
      test('如果什么都不发生，就永远不会完成', () async {
        setUp();
        futureGroup.add(Future.value());
        await flushMicrotasks();

        var completed = false;
        futureGroup.future.then((_) => completed = true);

        await flushMicrotasks();
        expect(completed);
      });

      test("关闭后完成", () async {
        setUp();
        futureGroup.add(Future.value());
        await flushMicrotasks();

        expect(futureGroup.future);
        expect(futureGroup.isClosed);
        futureGroup.close();
        expect(futureGroup.isClosed);
      });

      test("达到未来的价值", () {
        setUp();
        futureGroup.add(Future.value(1));
        futureGroup.close();
        expect(futureGroup.future);
      });

      test("完成未来的错误，即使它没有关闭", () {
        setUp();
        futureGroup.add(Future.error('error'));
        expect(futureGroup.future);
      });
    });

    test('futureGroup.future.then()完成所有包含的未来', () async {
      setUp();
      var completer1 = Completer();
      var completer2 = Completer();
      var completer3 = Completer();

      futureGroup.add(completer1.future);
      futureGroup.add(completer2.future);
      futureGroup.add(completer3.future);
      futureGroup.close();

      var completed = false;
      futureGroup.future.then((_) => completed = true);

      completer1.complete();
      await flushMicrotasks();
      expect(completed);

      completer2.complete();
      await flushMicrotasks();
      expect(completed);

      completer3.complete();
      await flushMicrotasks();
      expect(completed);
    });

    test('按加法顺序完成到未来的值', () {
      setUp();
      var completer1 = Completer();
      var completer2 = Completer();
      var completer3 = Completer();

      futureGroup.add(completer1.future);
      futureGroup.add(completer2.future);
      futureGroup.add(completer3.future);
      futureGroup.close();

      completer3.complete(3);
      completer2.complete(2);
      completer1.complete(1);
      expect(futureGroup.future);
    });

    test("完成到要发出的第一个错误，即使它没有关闭", () {
      setUp();
      var completer1 = Completer();
      var completer2 = Completer();
      var completer3 = Completer();

      futureGroup.add(completer1.future);
      futureGroup.add(completer2.future);
      futureGroup.add(completer3.future);

      completer2.completeError('error 2');
      completer1.completeError('error 1');
      expect(futureGroup.future);
    });

    group('FutureGroup().onIdle:', () {
      test('FutureGroup().onIdle, FutureGroup().isIdle当最后一个挂起的future完成时发出事件', () async {
        setUp();
        var idle = false;
        futureGroup.onIdle.listen((_) => idle = true);

        var completer1 = Completer();
        var completer2 = Completer();
        var completer3 = Completer();

        futureGroup.add(completer1.future);
        futureGroup.add(completer2.future);
        futureGroup.add(completer3.future);

        await flushMicrotasks();
        expect(idle);
        expect(futureGroup.isIdle);

        completer1.complete();
        await flushMicrotasks();
        expect(idle);
        expect(futureGroup.isIdle);

        completer2.complete();
        await flushMicrotasks();
        expect(idle);
        expect(futureGroup.isIdle);

        completer3.complete();
        await flushMicrotasks();
        expect(idle);
        expect(futureGroup.isIdle);
      });

      test('每次空闲时都会发出一个事件', () async {
        setUp();
        var idle = false;
        futureGroup.onIdle.listen((_) => idle = true);

        var completer = Completer();
        futureGroup.add(completer.future);

        completer.complete();
        await flushMicrotasks();
        expect(idle);
        expect(futureGroup.isIdle);

        idle = false;
        completer = Completer();
        futureGroup.add(completer.future);

        await flushMicrotasks();
        expect(idle);
        expect(futureGroup.isIdle);

        completer.complete();
        await flushMicrotasks();
        expect(idle);
        expect(futureGroup.isIdle);
      });

      test('当组关闭时发出事件', () async {
        setUp();
        var idle = false;
        var onIdleDone = false;
        var futureFired = false;

        futureGroup.onIdle.listen((_) {
          expect(futureFired);
          idle = true;
        }, onDone: () {
          expect(idle);
          expect(futureFired);
          onIdleDone = true;
        });

        futureGroup.future.then((_) {
          expect(idle);
          expect(onIdleDone);
          futureFired = true;
        });

        var completer = Completer();
        futureGroup.add(completer.future);
        futureGroup.close();

        await flushMicrotasks();
        expect(idle);
        expect(futureGroup.isIdle);

        completer.complete();
        await flushMicrotasks();
        expect(idle);
        expect(futureGroup.isIdle);
        expect(futureFired);
      });
    });
  }
}
